package com.ebook.server.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.ebook.core.domain.Book;
import com.ebook.core.domain.Note;
import com.ebook.core.util.NoteUtil;
import com.ebook.util.DateUtil;
import com.ebook.util.ErrorCode;
import com.ebook.util.Status;
import com.ebook.util.UpAndDown;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@Service
@Transactional
public class NoteService {

	@Resource
	private JdbcTemplate jdbcTemplate;

	@Resource
	private BookService bookService;

	@Resource
	private UserService userService;

	private static final String NOTE_FILE_PATH = "/opt/ebook/data/note/";

	/**
	 * 将读书笔记同步到服务器，并将笔记zip文件包上传到文件服务器上
	 * @param noteFile  zip文件包
	 * @param uid       用户id
	 * @param noteData  笔记数据
	 * @param request
	 * @return          成功，失败信息
	*/
	public ModelAndView addNoteToServer(MultipartFile noteFile, int uid, String noteData, HttpServletRequest request) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.SUCCESS;
		//		User user = (User) request.getSession().getAttribute("loginuser");
		//				if (user == null || uid != user.getId()) {
		//					return userService.notLoginView(modelView, modelMap);
		//				}
		//		 if (uid == user.getId()) {
		Gson gson = new Gson();
		List<Note> notelist = gson.fromJson(noteData, new TypeToken<List<Note>>() {
		}.getType());
		Book book = bookService.getBookInfo(notelist.get(0).getBookid());
		if (book == null) {
			status = Status.REJECTED + ":" + ErrorCode.BOOK_NOT_EXIST;
		} else {
			if (!addNote(uid, notelist.get(0))) {
				status = Status.REJECTED + ":" + ErrorCode.NOTE_ADD_FAIL;
			} else {
				if (noteFile != null) {
					String toFilePath = getFilePath(uid, notelist.get(0).getBookid(), notelist.get(0).getNoteid(),request);
					writeNote(noteFile, notelist.get(0), toFilePath);
				}
				modelMap.put("noteId", notelist.get(0).getNoteid());
			}
		}
		//		}
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	/**
	 * 根据笔记id删除一条笔记 和 服务器zip文件包
	 * @param noteIdsJson 笔记ids
	 * @param uid         用户id
	 * @param request
	 * @return            删除成功、失败信息
	 */
	public ModelAndView delNoteAndZip(String noteIdsJson, int uid,int bookid, HttpServletRequest request) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.SUCCESS;
		//		User user = (User) request.getSession().getAttribute("loginuser");
		//				if (user == null || uid != user.getId()) {
		//					return userService.notLoginView(modelView, modelMap);
		//				}
		//		if (uid == user.getId()) {
		List<Note> list = new Gson().fromJson(noteIdsJson, new TypeToken<List<Note>>() {
		}.getType());
		if (isNoteExist(list)) {
			status = Status.REJECTED + ":" + ErrorCode.NOTE_NOT_EXIST;
		} else {
			if (deleteNoteByNoteid(list) == false) {
				status = Status.REJECTED + ":" + ErrorCode.NOTE_DEL_FAIL;
			} else {
				deleteNoteZip(list, uid,bookid,request);
			}
		}
		//		}
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	/**
	 * 根据本地有的noteid和update_time，获取相应的笔记信息
	 * @param uid        用户id
	 * @param bookid     图书id
	 * @param noteJson   存的是本地有 的noteid和update_time
	 * @param request
	 * @return
	 */
	public ModelAndView getNoteData(int uid, int bookid, String noteJson, HttpServletRequest request) {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		List<Note> list = new ArrayList<Note>();
		String status = Status.SUCCESS;
		//		User user = (User) request.getSession().getAttribute("loginuser");
		//		if (user == null || uid != user.getId()) {
		//			return userService.notLoginView(modelView, modelMap);
		//		}
		//		if (uid == user.getId()) {
		Gson gson = new Gson();
		List<Note> notelist = gson.fromJson(noteJson, new TypeToken<List<Note>>() {
		}.getType());
		list = getNoteFromServer(uid, bookid, notelist);
		modelMap.put("notelist", list);
		//		}
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	/**
	 * 通过uid和noteid获取服务器相对应的zip文件包
	 * @param uid       用户id
	 * @param bookid    图书id
	 * @param noteid    笔记id
	 * @param request   
	 * @return 成功、失败信息
	 * @throws Exception
	 */
	public ModelAndView getNoteZipFromServer(int uid, int bookid, String noteid, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ModelAndView modelView = new ModelAndView();
		Map<String, Object> modelMap = new HashMap<String, Object>();
		String status = Status.SUCCESS;
		//		User user = (User) request.getSession().getAttribute("loginuser");
		//				if (user == null || uid != user.getId()) {
		//					return userService.notLoginView(modelView, modelMap);
		//				}
		//		 if (uid == user.getId()) {
		String filePath = getFilePath(uid, bookid, noteid,request);
		if (!UpAndDown.downloadZip(filePath, request, response)) {
			status = Status.REJECTED + ":" + ErrorCode.NOTE_GETZIP_FAIL;
		} else {
			modelMap.put("noteid", noteid);
		}
		//		 }
		modelMap.put("status", status);
		modelView.addAllObjects(modelMap);
		return modelView;
	}

	/**
	 * 获取文件的地址
	 * 格式：/opt/ebook/data/note/bookid/uid_noteid.zip
	 * @param uid
	 * @param bookid
	 * @param noteid
	 * @return 文件地址
	*/
	private String getFilePath(int uid, int bookid, String noteid,HttpServletRequest request) {
		
		File f=new File(NOTE_FILE_PATH + bookid);
		 if(!f.exists()){
		   f.mkdirs();
		  }
		return NOTE_FILE_PATH + bookid + "/" + uid + "_" + noteid.trim() + ".zip";

	}

	/**
	 * 将笔记信息上传到服务器。
	 * if(noteid存在 && update_time是最新的) 更新上传；
	 * if(noteid 不存在) 插入上传；
	 * @param uid   用户id
	 * @param note  note对象(笔记信息)
	 * @return true:上传成功；false:上传失败
	*/
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	private boolean addNote(int uid, Note note) {
		String selectSql = "select count(*)as count,update_time from note where noteid=? ";
		System.out.println(selectSql);
		Map<String, Object> map = jdbcTemplate.queryForMap(selectSql, note.getNoteid());
		if (((Long) map.get("count")) > 0) {
			if (DateUtil.compare_date(note.getUpdate_time().toString(), map.get("update_time").toString())) {
				String updateSql = "update note set create_time=?,update_time=?,curr_chapter=?,select_content=?,"
						+ "note_content=?,contain_file=?,startCFI=?,endCFI=?,note_index=?,isNote=?,color=?,div_status=? where noteid=?";
				System.out.println(updateSql);
				jdbcTemplate.update(
						updateSql,
						new Object[] { note.getCreate_time(), note.getUpdate_time().toString(), note.getCurr_chapter(),
								note.getSelect_content(), note.getNote_content(), note.getContain_file(),
								note.getStartCFI(), note.getEndCFI(), note.getNote_index(), note.getIsNote(),
								note.getColor(), note.getDiv_status(), note.getNoteid() });
			}
		} else {
			String insertSql = "insert into note (noteid,bookid,uid,create_time,update_time,curr_chapter,"
					+ "select_content,note_content,issynronezed,contain_file,startCFI,endCFI,note_index,isNote,color,div_status)"
					+ " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
			System.out.println(insertSql);
			jdbcTemplate.update(
					insertSql,
					new Object[] { note.getNoteid(), note.getBookid(), note.getUid(), note.getCreate_time(),
							note.getUpdate_time().toString(), note.getCurr_chapter(), note.getSelect_content(),
							note.getNote_content(), 1, note.getContain_file(), note.getStartCFI(), note.getEndCFI(),
							note.getNote_index(), note.getIsNote(), note.getColor(), note.getDiv_status() });
		}
		return true;
	}

	/**
	 * 根据noteId 删除一条笔记
	 * @param noteIds 笔记ids
	 * @return 成功信息
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public boolean deleteNoteByNoteid(List<Note> noteIds) {
		String sql = "delete from note where noteid = ?";
		System.out.println(sql);
		for (int i = 0; i < noteIds.size(); i++) {
			jdbcTemplate.update(sql, noteIds.get(i).getNoteid());
		}
		return true;
	}

	@Transactional(readOnly = true)
	public boolean isNoteExist(List<Note> noteIds) {
		String SelectSql = "select count(*) from note where noteid =?";
		System.out.println(SelectSql);
		for (int i = 0; i < noteIds.size(); i++) {
			if (jdbcTemplate.queryForInt(SelectSql, noteIds.get(i).getNoteid()) == 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 将笔记zip文件包上传到服务器的目录里
	 * @param noteFile 笔记zip文件包
	 * @param noteData 笔记对象
	 * @return true：成功；false：失败
	 */
	private boolean writeNote(MultipartFile noteFile, Note noteData, String toFilePath) {
		try {
			System.out.println("writeto: "+toFilePath);
			File outfile = new File(toFilePath);
			if (!outfile.exists()){
				if (!outfile.createNewFile())
					return false;
			}	
			FileOutputStream fs = new FileOutputStream(outfile);
			byte[] buffer = new byte[1024 * 1024];
			int bytesum = 0;
			int byteread = 0;
			InputStream stream = noteFile.getInputStream();
			while ((byteread = stream.read(buffer)) != -1) {
				bytesum += byteread;
				fs.write(buffer, 0, byteread);
				fs.flush();
			}
			fs.close();
			stream.close();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}

		return true;

	}

	/**
	 * 根据算法获取笔记信息
	 * 算法：TODO
	 * @param uid      用户id
	 * @param bookid   图书id
	 * @param list     多条笔记信息
	 * @return 笔记信息
	*/
	public List<Note> getNoteFromServer(int uid, int bookid, List<Note> list) {
		List<Note> noteList = new ArrayList<Note>();
		String selectNoteidSql = "select * from note where uid=? and bookid=? and noteid=? ";
		System.out.println(selectNoteidSql);
		for (Note n : list) {
			List<Map<String, Object>> maps = jdbcTemplate.queryForList(selectNoteidSql, uid, bookid, n.getNoteid()
					.toString());
			if (maps.size() > 0) {
				for (Map<String, Object> map : maps) {
					if (DateUtil.compare_date(map.get("update_time").toString(), n.getUpdate_time())) {
						Note note = NoteUtil.parseNote(map);
						if (note != null) {
							noteList.add(note);
						}
					}
				}
			}
		}
		StringBuilder selectNoNoteidSql = new StringBuilder("select * from note where uid=? and bookid=?");
		for (int i = 0; i < list.size(); i++) {
			selectNoNoteidSql.append(" and noteid!='").append(list.get(i).getNoteid()).append("'");
		}
		System.out.println(selectNoNoteidSql);
		List<Map<String, Object>> maps1 = jdbcTemplate.queryForList(selectNoNoteidSql.toString(), uid, bookid);
		for (Map<String, Object> map : maps1) {
			Note note = NoteUtil.parseNote(map);
			if (note != null) {
				noteList.add(note);
			}
		}
		return noteList;

	}


	/**
	 * 根据 笔记Id 删除服务器zip文件包
	 * @param noteIds 笔记Ids
	 * @param uid     用户id
	 */
	public void deleteNoteZip(List<Note> noteIds, int uid,int bookid,HttpServletRequest request) {
		for (Note n : noteIds) {
			String filePath = getFilePath(uid,bookid, n.getNoteid(),request);
			System.out.println("delete: "+filePath);
			File fileZip = new File(filePath);
			if (!fileZip.exists()) {
				System.out.println("fileZip:" + uid + "_" + n.getNoteid() + ".zip is not present");
			} else {
				fileZip.delete();
			}
		}
	}
}
